package com.icee.myth.manager.channelHandler;

import com.icee.myth.manager.Manager;
import com.icee.myth.utils.Consts;
import com.icee.myth.utils.LogConsts;
import com.icee.myth.utils.MLogger;
import com.icee.myth.utils.StackTraceUtil;
import io.netty.channel.*;
import io.netty.handler.ssl.SslHandler;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.GenericFutureListener;
import org.apache.commons.io.FileUtils;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

/**
 *
 * @author liuxianke
 */
public class BootstrapToManagerHandler extends ChannelInboundHandlerAdapter {

    @Override
    public void channelActive(final ChannelHandlerContext ctx) throws Exception {
        super.channelActive(ctx);

        // Get the SslHandler in the current pipeline.
        // We added it in SecureChatPipelineFactory.
        final SslHandler sslHandler = ctx.pipeline().get(SslHandler.class);

        // Get notified when SSL handshake is done.
        Future<Channel> handshakeFuture = sslHandler.handshakeFuture();     //handshake();
        handshakeFuture.addListener(new GenericFutureListener<Future<Channel>>() {
            @Override
            public void operationComplete(Future<Channel> future) throws Exception {
                ChannelFuture writeFuture = null;

                if (future.isSuccess()) {
                    if (Manager.INSTANCE.mode == Consts.START_MODE_REMOTE) {
                        writeFuture = ctx.channel().write(Manager.INSTANCE.sourceData);   //future.channel().write(Manager.INSTANCE.sourceData);
                    } else {
                        // Once session is secured, send JAR file
                        File jarFile = new File(Manager.INSTANCE.serverJarFileName);
                        int remainLen = (int)FileUtils.sizeOf(jarFile);

                        FileInputStream fis = null;
                        try {
                            fis = FileUtils.openInputStream(jarFile);
                            while (remainLen > 0) {
                                int bufLen = (remainLen > 1024)?1024:remainLen;
                                byte[] buf = new byte[bufLen];
                                int readedLen = 0;
                                while (readedLen < bufLen) {
                                    readedLen += fis.read(buf, readedLen, bufLen-readedLen);
                                }
                                writeFuture = ctx.channel().write(buf);     //future.channel().write(buf);
                                remainLen -= bufLen;
                            }
                        }catch (IOException e){
                            e.printStackTrace();
                        }catch (Exception e){
                            e.printStackTrace();
                        }finally {
                            if(null != fis){
                                try {
                                    fis.close();
                                }catch (Exception e){
                                    e.printStackTrace();
                                }
                            }
                        }
                    }
                }

                if (writeFuture != null) {
                    writeFuture.addListener(new ChannelFutureListener() {
                        @Override
                        public void operationComplete(ChannelFuture future) throws Exception {
                            future.channel().close();
                        }
                    });
                } else {
                    ctx.channel().close();        //future.channel().close();
                }
            }
        });
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        super.channelInactive(ctx);
        MLogger.getlogger().log(LogConsts.LOGTYPE_DEBUG, "Bootstrap channel disconnected.");
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        super.channelReadComplete(ctx);
        MLogger.getlogger().log(LogConsts.LOGTYPE_DEBUG, "Manager receive something from bootstrap.");
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        MLogger.getlogger().debuglog(LogConsts.LOGLEVEL_DEBUG, StackTraceUtil.getStackTrace(cause));
        ctx.channel().close();
    }
}
